package com.hzgj.bcl.soa.config;

import com.google.common.collect.Lists;

import com.hzgj.bcl.annotations.Comment;
import com.hzgj.bcl.soa.util.Pair;
import com.hzgj.bcl.soa.util.Triple;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import static com.hzgj.bcl.soa.util.Constants.DEFAULT_PROTOCOL;
import static com.hzgj.bcl.soa.util.Constants.DEFAULT_REGISTRY;

/**
 * Created by dell on 2015/3/25.
 */

@ToString
public class ServiceDef implements Serializable {

    @Setter
    @Getter
    List<Attr> attrs = new ArrayList<>();
    @Setter
    @Getter
    private String name;

    public ServiceDef() {
    }


    public ServiceDef(String name, List<Attr> attrs) {
        this.name = name;
        this.attrs = attrs;
    }

    public static ServiceInfo getServiceInfo(String className) {
        ServiceInfo serviceInfo = new ServiceInfo();
        try {
//            List<MethodInfo> methodInfos = Lists.newArrayList();
            Class<?> service = Thread.currentThread().getContextClassLoader().loadClass(className);
            Comment cm = service.getAnnotation(Comment.class);
            if (cm != null) {
                serviceInfo.setComment(cm.value());
            }
//            serviceInfo.setMethodInfos(methodInfos);
//            for (Method method : service.getMethods()) {
//                MethodInfo methodInfo = new MethodInfo();
//                Comment mc = method.getAnnotation(Comment.class);
//                if (mc == null) continue;
//                methodInfo.setMethod(new Pair<>(method.getName(), mc.value()));
//                methodInfo.setRet(new Pair<>(method.getReturnType().getName(), mc.ret()));
//                if (mc.params() != null && mc.params().length == method.getParameterCount()) {
//                    List<Triple<String, String, String>> params = Lists.newArrayList();
//                    int i = 0;
//                    for (Parameter parameter : method.getParameters()) {
//                        params.add(new Triple<>(parameter.getName(), parameter.getParameterizedType().getTypeName(), mc.params()[i]));
//                        i++;
//                    }
//                    methodInfo.setParameters(params);
//                } else {
//                    throw new RuntimeException("@Comment param count is invalidate.");
//                }
//                methodInfos.add(methodInfo);
//            }
        } catch (ClassNotFoundException e) {
        }
        return serviceInfo;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        ServiceDef that = (ServiceDef) o;
        return !(name != null ? !name.equals(that.name) : that.name != null);
    }

    @Override
    public int hashCode() {
        return name != null ? name.hashCode() : 0;
    }

    @Data
    public static class MethodInfo implements Serializable {
        private Pair<String, String> method;
        private List<Triple<String, String, String>> parameters;
        private Pair<String, String> ret;
    }

    @Data
    public static class ServiceInfo {
        private String comment;
        private String name;
        private int providers;
        private int consumes;
        private List<MethodInfo> methodInfos = Lists.newArrayList();

        @Override
        public String toString() {
            return "ServiceInfo{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }


    @Getter
    @Setter
    public static class BaseServiceAttr implements Serializable {
        protected String id;
        protected String note;
        protected String version;
        protected Date time;
        protected String group;
        protected String interfaceClass;
        protected String protocol = DEFAULT_PROTOCOL;
        protected String ref;
        protected boolean register = DEFAULT_REGISTRY;
        protected String author;
        protected ServerDef serverDef;
        protected String domain;
        protected String application;

        public String getServer() {
            if (serverDef == null) {
                return null;
            }
            return serverDef.getId();
        }

        public void setServer(String server) {
            serverDef = new ServerDef(server);
        }
    }

    @Getter
    @Setter
    public static class Attr extends BaseServiceAttr {

        protected Map<String, MethodDef> methodDefs;

        public String getInterface() {
            return interfaceClass;
        }

        public void setInterface(String interfaceClass) {
            this.interfaceClass = interfaceClass;
        }

        @Override
        public String toString() {
            return "Attr{" +
                    "id='" + id + '\'' +
                    ", note='" + note + '\'' +
                    ", version='" + version + '\'' +
                    ", time=" + time +
                    ", group='" + group + '\'' +
                    ", interfaceClass='" + interfaceClass + '\'' +
                    ", protocol='" + protocol + '\'' +
                    ", ref='" + ref + '\'' +
                    ", register=" + register +
                    ", serverDef=" + serverDef +
                    '}';
        }
    }
}
